#pragma once
#include <set>
#include <atomic>
#include <mutex>
#include "VCBase.h"

class CRefCount
{
public:
    CRefCount() : m_ref_count(0) {}
    ~CRefCount()
    {
        for (auto pItem : m_visitorSet)
        {
            pItem->Destory();
        }
        m_visitorSet.clear();
    }
public:
    void AddRef() const
    {
        ++m_ref_count;
    }
    bool Release() const
    {
        return --m_ref_count == 0;
    }

    void RegisterWeakVisitor(IWeakVisitor* pVisitor) const
    {
        std::lock_guard<std::recursive_mutex> lck(m_visitor_mutex);
        m_visitorSet.insert(pVisitor);
    }
    void UnRegisterWeakVisitor(IWeakVisitor* pVisitor) const
    {
        std::lock_guard<std::recursive_mutex> lck(m_visitor_mutex);
        m_visitorSet.erase(pVisitor);
    }

private:
    mutable std::recursive_mutex m_visitor_mutex;
    mutable std::atomic<int32_t> m_ref_count;
    mutable std::set<IWeakVisitor*> m_visitorSet;

    DISALLOW_COPY_AND_ASSIGN(CRefCount);
};

#define IMPLEMENT_REFCOUNTING(ClassName)            \
  public:                                           \
    void AddRef() const override {                  \
      ref_count_.AddRef();                          \
    }                                               \
    bool Release() const override {                 \
      if (ref_count_.Release()) {                   \
        delete static_cast<const ClassName*>(this); \
        return true;                                \
      }                                             \
      return false;                                 \
    }                                               \
    void RegisterWeakVisitor(IWeakVisitor* pVisitor) const override { \
		ref_count_.RegisterWeakVisitor(pVisitor);			 \
	}														 \
    void UnRegisterWeakVisitor(IWeakVisitor* pVisitor) const override { \
		ref_count_.UnRegisterWeakVisitor(pVisitor);			 \
	}														 \
private:\
    CRefCount ref_count_;

